package com.lantosec.hmrp.modules.notify.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lantosec.hmrp.core.config.InitDataListener;
import com.lantosec.hmrp.core.shiro.TokenUtil;
import com.lantosec.hmrp.core.util.DateUtils;
import com.lantosec.hmrp.core.util.UUIDUtils;
import com.lantosec.hmrp.core.util.sms.SmsUtils;
import com.lantosec.hmrp.core.util.sms.SubmitResult;
import com.lantosec.hmrp.core.websocket.WebSocketServer;
import com.lantosec.hmrp.modules.notify.entity.*;
import com.lantosec.hmrp.modules.notify.mapper.NotifyInfoMapper;
import com.lantosec.hmrp.modules.notify.service.INotifyInfoService;
import com.lantosec.hmrp.modules.notify.service.INotifyPublicReadService;
import com.lantosec.hmrp.modules.notify.service.INotifyTypeService;
import com.lantosec.hmrp.modules.notify.vo.NotifyInfoVO;
import com.lantosec.hmrp.modules.notify.vo.NotifyTypeVO;
import com.lantosec.hmrp.modules.system.entity.SendMessageBean;
import com.lantosec.hmrp.modules.system.entity.SysUser;
import com.lantosec.hmrp.modules.system.service.ISysSmsService;
import com.lantosec.hmrp.modules.system.service.ISysUserService;
import com.lantosec.hmrp.modules.uploads.entity.SysUploads;
import com.lantosec.hmrp.modules.uploads.service.ISysUploadsService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static com.lantosec.hmrp.core.util.BeanUtils.entity2VO;

/**
 * <p>
 * 通知 服务实现类
 * </p>
 *
 * @author AutoCode
 * @since 2020-05-22
 */
@Service
@Primary
@Log4j2
public class NotifyInfoServiceImpl extends ServiceImpl<NotifyInfoMapper, NotifyInfo> implements INotifyInfoService {
    @Autowired
    private ISysUploadsService iSysUploadsService;

    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private INotifyTypeService iNotifyTypeService;

    @Autowired
    private INotifyPublicReadService iNotifyPublicReadService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ISysSmsService iSysSmsService;

    @Override
    @Transactional
    public void saveNotifyInfo(NotifyInfoVO notifyInfoVO) {
        //当选择的时公告时
        if(notifyInfoVO.getPublicTag() == 1){
            //新建系统公告
            savePublicRead(notifyInfoVO);
        }else {
            //新建系统通知
            saveNotify(notifyInfoVO);
        }
    }

    private void savePublicRead(NotifyInfoVO notifyInfoVO) {
        //新增系统公告基本信息
        notifyInfoVO.setNotifyId(UUIDUtils.get());
        //获取当前用户id
        String userId = TokenUtil.getUserId();
        notifyInfoVO.setSenderId(userId);
        //当为及时发送时
        if(notifyInfoVO.getScheduleTag() == 0){
            notifyInfoVO.setSendTime(DateUtils.nowDate());
        }
        //获取当前用户名称
        String userName = TokenUtil.getName();
        notifyInfoVO.setSender(userName);
        notifyInfoVO.setNotifyTypeId("001");
        this.save(notifyInfoVO.convertToEntity());

        //新增公告内容
        NotifyContent notifyContent = new NotifyContent();
        notifyContent.setContent(notifyInfoVO.getContent());
        notifyContent.setNotifyId(notifyInfoVO.getNotifyId());
        baseMapper.insertNotifyContent(notifyContent);
        //新增公告附件
        List<NotifyAttachment> notifyAttachmentList = notifyInfoVO.getNotifyAttachmentList();
        if(null != notifyAttachmentList && notifyAttachmentList.size() > 0){
            notifyAttachmentList.forEach(param1->{
                param1.setNotifyId(notifyInfoVO.getNotifyId());
                baseMapper.insertNotifyAttachment(param1);
            });
        }
    }

    private void saveNotify(NotifyInfoVO notifyInfoVO) {
        //新增通知基本信息
        notifyInfoVO.setNotifyId(UUIDUtils.get());
        //获取当前用户id
        String userId = TokenUtil.getUserId();
        notifyInfoVO.setSenderId(userId);
        //获取当前用户名称
        String userName = TokenUtil.getName();
        notifyInfoVO.setSender(userName);
        //当为及时发送时
        if(notifyInfoVO.getScheduleTag() == 0){
            notifyInfoVO.setSendTime(DateUtils.nowDate());
        }
        this.save(notifyInfoVO.convertToEntity());
        //新增通知内容
        NotifyContent notifyContent = new NotifyContent();
        notifyContent.setContent(notifyInfoVO.getContent());
        notifyContent.setNotifyId(notifyInfoVO.getNotifyId());
        baseMapper.insertNotifyContent(notifyContent);
        //新增通知附件
        List<NotifyAttachment> notifyAttachmentList = notifyInfoVO.getNotifyAttachmentList();
        if(null != notifyAttachmentList && notifyAttachmentList.size() > 0){
            notifyAttachmentList.forEach(param1->{
                param1.setNotifyId(notifyInfoVO.getNotifyId());
                baseMapper.insertNotifyAttachment(param1);
            });
        }
        List<String> userList = new ArrayList<>();
        //当选择的是部门
        if(notifyInfoVO.getMesType()==1){
            String[] deptId = notifyInfoVO.getRecipientId().split(",");
            userList = baseMapper.getUserByDeptId(deptId);
        }
        //当选择的是岗位
        if(notifyInfoVO.getMesType()==2){
            String[] positionId = notifyInfoVO.getRecipientId().split(",");
            userList = baseMapper.getUserByPositionId(positionId);
        }
        //当选择的是人员
        if(notifyInfoVO.getMesType()==3){
            String[] recipientIds = notifyInfoVO.getRecipientId().split(",");
            userList =  Arrays.asList(recipientIds);
        }
        userList.forEach(user->{
            //新增系统通知接受人
            NotifyRecipient notifyRecipient = new NotifyRecipient();
            notifyRecipient.setNotifyId(notifyInfoVO.getNotifyId());
            notifyRecipient.setRecipientId(user);
            //查询用户名称
            String name = iSysUserService.getById(user).getName();
            notifyRecipient.setRecipient(name);
            baseMapper.insertNotifyRecipient(notifyRecipient);
            //当为及时发送时
            if(notifyInfoVO.getScheduleTag() == 0){
                notifyInfoVO.setSendTime(DateUtils.nowDate());
                try {
                    //PC端发送
                    WebSocketServer.sendInfo(notifyInfoVO.getTitle(),user);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        sendApiCloud(notifyInfoVO.getTitle(),notifyInfoVO.getDescription(), userList);
    }

    private void sendApiCloud(String title, String description, List<String> userList) {
        String[] userIds = new String[userList.size()];
        for(int i=0;i<userList.size();i++){
            userIds[i] = "K004:"+userList.get(i)+",";
            if(i == userList.size()-1){
                userIds[i] = "K004:"+userList.get(i);
            }
        }
        //APP端发送到APICloud
        //设置Http的Header
        HttpHeaders headers = new HttpHeaders();
        //当前时间毫秒数
        long now=System.currentTimeMillis();
        String appKey = "A6037792175698"+"UZ"+"B52A2C8D-175D-7738-A696-7B50B0B65DD6"+"UZ"+now;
        try {
            appKey = jdkSHA1(appKey)+"."+now;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        headers.set("X-APICloud-AppId","A6037792175698");
        headers.set("X-APICloud-AppKey",appKey);
        headers.setContentType(MediaType.APPLICATION_JSON);
        //设置访问参数
        HashMap<String, Object> body = new HashMap<>();
        body.put("title",title);
        body.put("content",description);
        body.put("type",2);  //消息1，通知2
        body.put("platform",2);//ios 1,Android 2
        body.put("userIds","k004:"+userIds);
        HttpEntity entity = new HttpEntity<>(body, headers);
        ResponseEntity<String> result = restTemplate.exchange("https://p.apicloud.com/api/push/message", HttpMethod.POST,entity, String.class);
        if(result.getStatusCode().value() == 1){
            log.info("发送成功！！！");
        }else {
            log.error("发送失败！！！");
        }

    }

    /**
     * 加密
     * @param appKey
     * @return
     */
    public String jdkSHA1(String appKey) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA1");
        md.update(appKey.getBytes());
        return Hex.encodeHexString(md.digest());
    }

    @Override
    public List<NotifyInfoVO> getNotRead(String notifyTypeId) {
        //获取当前用户id
        String userId = TokenUtil.getUserId();
        //查询当前用户的未读通知
        List<NotifyInfoVO> notifyInfoVOList = baseMapper.getNotReadNotifyInfo(notifyTypeId,userId);
        notifyInfoVOList = getNotifyInfo(notifyInfoVOList);
        return notifyInfoVOList;
    }

    @Override
    public int countNotRead(String userId, String notifyTypeId) {
        //查询当前用户的未读通知
        return baseMapper.countNotReadNotifyInfo(notifyTypeId, userId);
    }

    @Override
    public List<NotifyInfoVO> getRead(String notifyTypeId) {
        //获取当前用户id
        String userId = TokenUtil.getUserId();
        //查询当前用户的未读通知
        List<NotifyInfoVO> notifyInfoVOList = baseMapper.getReadNotifyInfo(notifyTypeId,userId);
        notifyInfoVOList = getNotifyInfo(notifyInfoVOList);
        return notifyInfoVOList;
    }

    @Override
    public void updateRead(List<NotifyRecipient> notifyRecipientList) {
        notifyRecipientList.forEach(param->{
            param.setReadFlag(1);
            //获取当前用户id
            String userId = TokenUtil.getUserId();
            param.setRecipientId(userId);
            param.setReadTime(DateUtils.nowDate());
            baseMapper.updateNotifyRecipient(param);
        });

    }

    @Override
    public void updateDelete(List<NotifyRecipient> notifyRecipientList) {
        notifyRecipientList.forEach(param->{
            param.setReadFlag(1);
            param.setDeleteFlag(1);
            //获取当前用户id
            String userId = TokenUtil.getUserId();
            param.setRecipientId(userId);
            param.setReadTime(DateUtils.nowDate());
            param.setDeleteTime(DateUtils.nowDate());
            baseMapper.updateNotifyRecipient(param);
        });
    }

    @Override
    public List<NotifyTypeVO> getAll() {
        //查询所有的通知类型
        List<NotifyType> notifyTypeList = iNotifyTypeService.list();
        List<NotifyTypeVO> notifyTypeVOList = entity2VO(notifyTypeList);
        notifyTypeVOList.forEach(param->{
            String notifyTypeId = param.getNotifyTypeId();
            //查询通知类型下的通知详细信息
            //获取当前用户id
            String userId = TokenUtil.getUserId();
            List<NotifyInfoVO> notifyInfoVOList= baseMapper.getAll(notifyTypeId,userId);
            notifyInfoVOList = getNotifyInfo(notifyInfoVOList);
            param.setNotifyInfoVOList(notifyInfoVOList);
        });
        return notifyTypeVOList;
    }

    @Override
    public List<NotifyInfoVO> get(String notifyTypeId) {
        //查询通知类型下的通知详细信息
        //获取当前用户id
        String userId = TokenUtil.getUserId();
        List<NotifyInfoVO> notifyInfoVOList= baseMapper.getAll(notifyTypeId,userId);
        notifyInfoVOList = getNotifyInfo(notifyInfoVOList);
        return notifyInfoVOList;
    }

    @Override
    public List<NotifyInfoVO> getPublicRead() {
        //查询当前用户所收到的公告信息
        List<NotifyInfoVO> notifyInfoList = baseMapper.getPublicRead();
        List<NotifyInfoVO> notifyInfoVOList = new ArrayList<>();
        notifyInfoList.forEach(param->{
            List<NotifyPublicRead> notifyPublicReadList = iNotifyPublicReadService.list(new QueryWrapper<NotifyPublicRead>().eq(NotifyPublicRead.ColName.notify_id.toString(),param.getNotifyId()));
            //如果当前用户没有看过公告信息则提醒有公告信息，反之不提醒
            if(null == notifyPublicReadList || notifyPublicReadList.size() <= 0){
                //查询通知附件
                List<NotifyAttachment> notifyAttachmentList =  baseMapper.getNotifyAttachment(param.getNotifyId());
                notifyAttachmentList.forEach(param1->{
                    String uploadId = param1.getUploadId();
                    //返回文件的存放路径
                    SysUploads sysUploads = iSysUploadsService.getById(uploadId);
                    param1.setSavePath(InitDataListener.uploadsUrl + sysUploads.getSavePath() + sysUploads.getFileName());
                });
                param.setNotifyAttachmentList(notifyAttachmentList);
                notifyInfoVOList.add(param);
            }
        });
        return notifyInfoVOList;
    }

    @Override
    public List<NotifyInfoVO> getPublicReadAll() {
        //查询当前用户所收到的公告信息
        List<NotifyInfoVO> notifyInfoList = baseMapper.getPublicRead();
        notifyInfoList.forEach(param->{
            //查询通知附件
            List<NotifyAttachment> notifyAttachmentList =  baseMapper.getNotifyAttachment(param.getNotifyId());
            notifyAttachmentList.forEach(param1->{
                String uploadId = param1.getUploadId();
                //返回文件的存放路径
                SysUploads sysUploads = iSysUploadsService.getById(uploadId);
                param1.setSavePath(InitDataListener.uploadsUrl + sysUploads.getSavePath() + sysUploads.getFileName());
            });
            param.setNotifyAttachmentList(notifyAttachmentList);
        });
        return notifyInfoList;
    }

    @Override
    public void noticeSending(NotifyInfoVO notifyInfoVO) {
        NotifyInfo notifyInfo = notifyInfoVO.convertToEntity();
        notifyInfo.setNotifyId(UUIDUtils.get());
        //查询发送人名称
        String senderId = notifyInfo.getSenderId();
        if(notifyInfo.getScheduleTag() == 0){
            notifyInfo.setSendTime(DateUtils.nowDate());
        }
        SysUser sysUser = iSysUserService.getById(senderId);
        if(Objects.nonNull(sysUser)){
            String name = sysUser.getName();
            if(StringUtils.isNotEmpty(name)){
                notifyInfo.setSender(name);
            }
        }
        this.save(notifyInfo);
        //PC端发送通知
        sendNotifyPc(notifyInfoVO);
        //当发送短信标识为1时
        if(notifyInfoVO.getSmsTag() == 1){
            senSms(notifyInfoVO);
        }

    }

    /**
     * 发送短信
     * @param notifyInfoVO
     */
    private void senSms(NotifyInfoVO notifyInfoVO) {
        String recipientId = notifyInfoVO.getRecipientId();
        //查询接受人手机号
        try {
            String phone = iSysUserService.getById(recipientId).getPhone();
            if(StringUtils.isNotEmpty(phone)){
                SubmitResult submitResult = SmsUtils.send(phone,notifyInfoVO.getContent());
                if(!Objects.isNull(submitResult)){
                    log.info("code:"+submitResult.getCode()+"--msg:"+submitResult.getMsg()+"--smsid:"+submitResult.getSmsid());
                    //存日志表
                    SendMessageBean sendMessageBean = new SendMessageBean();
                    sendMessageBean.setModuleId("workflow");
                    sendMessageBean.setSmsContent(notifyInfoVO.getContent());
                    sendMessageBean.setPhone(phone);
                    sendMessageBean.setSmsCode(String.valueOf(submitResult.getCode()));
                    iSysSmsService.saveSmsLog(sendMessageBean);
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * PC端发送通知
     * @param notifyInfoVO
     */
    private void sendNotifyPc(NotifyInfoVO notifyInfoVO) {
        //新增系统通知接受人
        NotifyRecipient notifyRecipient = new NotifyRecipient();
        notifyRecipient.setNotifyId(notifyInfoVO.getNotifyId());
        notifyRecipient.setRecipientId(notifyInfoVO.getRecipientId());
        if(StringUtils.isEmpty(notifyInfoVO.getRecipient())){
            //查询用户名称
            String recipientName = iSysUserService.getById(notifyInfoVO.getRecipientId()).getName();
            notifyRecipient.setRecipient(recipientName);
        }else{
            notifyRecipient.setRecipient(notifyInfoVO.getRecipient());
        }
        baseMapper.insertNotifyRecipient(notifyRecipient);
        //当为及时发送时
        if(notifyInfoVO.getScheduleTag() == 0){
            notifyInfoVO.setSendTime(DateUtils.nowDate());
            try {
                //PC端发送
                WebSocketServer.sendInfo(notifyInfoVO.getTitle(),notifyInfoVO.getRecipientId());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public Map<String, Object> getNotifySum(String notifyId) {
        Integer finishSum = baseMapper.getNotifyFinishSum(notifyId);
        Integer notFinishSum = baseMapper.getNotifyNotFinishSum(notifyId);
        Map<String, Object> map = new HashMap<>();
        map.put("finishSum",finishSum);
        map.put("notFinishSum",notFinishSum);
        return map;
    }

    private List<NotifyInfoVO> getNotifyInfo(List<NotifyInfoVO> notifyInfoVOList) {
        notifyInfoVOList.forEach(param->{
            String notifyId = param.getNotifyId();
            Map<String, Object> map = this.getNotifySum(notifyId);
            param.setMap(map);
            //查询通知内容
            NotifyContent notifyContent = baseMapper.getNotifyContent(notifyId);
            param.setContent(notifyContent.getContent());
            //查询通知附件
            List<NotifyAttachment> notifyAttachmentList =  baseMapper.getNotifyAttachment(notifyId);
            notifyAttachmentList.forEach(param1->{
                String uploadId = param1.getUploadId();
                //返回文件的存放路径
                SysUploads sysUploads = iSysUploadsService.getById(uploadId);
                param1.setSavePath(InitDataListener.uploadsUrl + sysUploads.getSavePath() + sysUploads.getFileName());
            });
            param.setNotifyAttachmentList(notifyAttachmentList);
        });
        return notifyInfoVOList;
    }
}
